package main

import "C"
import (
	"fmt"
	"log"
	"net"
	"sync" // 引入并发锁，确保线程安全
	"time"

	"golang.org/x/crypto/ssh"
)

// 定义一个全局变量来存储SSH客户端连接
var client *ssh.Client

// 使用互斥锁来保护全局客户端变量，防止多线程并发访问导致问题
var clientMutex sync.Mutex

// 连接到SSH服务器
//
//export Connect
func Connect(host *C.char, port C.int, user *C.char, password *C.char) C.int {
	clientMutex.Lock()
	defer clientMutex.Unlock()

	// 如果已经存在连接，先关闭
	if client != nil {
		client.Close()
		client = nil
	}

	cfg := &ssh.ClientConfig{
		User: C.GoString(user),
		Auth: []ssh.AuthMethod{
			ssh.Password(C.GoString(password)),
		},
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			// 在实际应用中，你应该验证主机密钥，这里为了简单直接返回nil
			return nil
		},
		Timeout: 5 * time.Second,
	}

	addr := fmt.Sprintf("%s:%d", C.GoString(host), port)
	var err error
	client, err = ssh.Dial("tcp", addr, cfg)
	if err != nil {
		log.Printf("Failed to dial to %s: %v\n", addr, err)
		return 1 // 返回非0表示失败
	}
	return 0 // 返回0表示成功
}

// 在现有SSH连接上发送命令
//
//export SendCommand
func SendCommand(command *C.char) *C.char {
	clientMutex.Lock()
	defer clientMutex.Unlock()

	if client == nil {
		log.Println("Error: SendCommand called but not connected to an SSH server.")
		return C.CString("Error: Not connected to an SSH server.")
	}

	session, err := client.NewSession()
	if err != nil {
		log.Printf("Failed to create new session: %v\n", err)
		return C.CString(fmt.Sprintf("Failed to create session: %v", err))
	}
	defer session.Close() // 确保会话在函数退出时关闭

	output, err := session.CombinedOutput(C.GoString(command))
	if err != nil {
		log.Printf("Failed to run command '%s': %v\n", C.GoString(command), err)
		// 如果命令执行失败，返回错误信息，而不是空指针
		return C.CString(fmt.Sprintf("Failed to run command: %v", err))
	}

	return C.CString(string(output))
}

// 断开SSH连接
//
//export Disconnect
func Disconnect() {
	clientMutex.Lock()
	defer clientMutex.Unlock()

	if client != nil {
		log.Println("Disconnecting SSH client...")
		client.Close()
		client = nil
	}
}

// main函数是cgo的必需项，但是不会被执行
func main() {}
